from tkinter import *
from tkinter import filedialog
from tkinter import ttk
from threading import Thread
from datetime import datetime, timedelta
from sql import MySQLDB
from myexcel import *
from mytools import *
from config import *
import tkinter.font
import tkinter.messagebox as messagebox
import openpyxl,concurrent.futures,math
import time,os,subprocess,uuid,traceback


class ProFrame(Frame):
    def __init__(self,master=None):
        Frame.__init__(self,master)
        dbdiv=DBFrame(self)
        dbdiv.pack(pady=3,fill=X,padx=3)
        FsbmsFrame(self,dbdiv).pack(pady=3,fill=X,padx=3)
        ZsbmsFrame(self,dbdiv).pack(pady=3,fill=X,padx=3)

class DBFrame(Frame):
    def __init__(self,master=None):
        Frame.__init__(self,master)
        self.login=False
        self.tables=[]
        self.createWidgets()
        Thread(target=self.getDB).start()

    def createWidgets(self):
        basic_info=get_allconfig()
        f0=Frame(self)
        f0.pack(fill=X,padx=2,pady=2)
        Label(f0, text='数据库信息', fg="white", bg="#007FFF",font=("微软雅黑", 13)).pack(fill=X,padx=5)

        f1=Frame(self)
        f1.pack(fill=X,padx=2,pady=2)
        f00=Frame(f1)
        f00.pack(fill=X,padx=2,pady=2)
        Label(f00, text='服务器地址:').pack(side=LEFT, padx=2, pady=2)
        self.DBHostIpt = Entry(f00,width=10)
        self.DBHostIpt.pack(side=LEFT, padx=2, pady=2)
        self.DBHostIpt.insert(0,basic_info['DB_HOST'])


        Label(f00, text='数据库账户:').pack(side=LEFT, padx=2, pady=2)
        self.DBUidIpt = Entry(f00,width=5)
        self.DBUidIpt.pack(side=LEFT, padx=2, pady=2)
        self.DBUidIpt.insert(0,basic_info['DB_UID'])

        
        Label(f00, text='数据库密码:').pack(side=LEFT, padx=2, pady=2)
        self.DBPwdIpt = Entry(f00)
        self.DBPwdIpt.pack(side=LEFT, padx=2, pady=2)
        self.DBPwdIpt.insert(0,basic_info['DB_PWD'])
        
        Label(f00, text='服务器端口:').pack(side=LEFT, padx=2, pady=2)
        self.DBPortIpt = Entry(f00,width=5)
        self.DBPortIpt.pack(side=LEFT, padx=2, pady=2)
        self.DBPortIpt.insert(0,basic_info['DB_PORT'])
        

        f01=Frame(f1)
        f01.pack(fill=X,padx=2,pady=2)
        
        Label(f01, text='选择数据库:').pack(side=LEFT, padx=2, pady=2)
        self.DBSelect = ttk.Combobox(f01,state='readonly')
        self.DBSelect['value'] = ['未加载']
        self.DBSelect.bind("<<ComboboxSelected>>", lambda e:Thread(target=self.change_db).start())
        self.DBSelect.pack(side=LEFT, padx=2, pady=2)
        self.DBSelect.current(0)

        self.btn_conenct=Button(f01,text='连接接服务器',command=lambda:Thread(target=self.connect_server).start(),fg='#ffffff',bg='green')
        self.btn_conenct.pack(side=LEFT,padx=2, pady=2)


    def getDB(self):

        basic_info=get_allconfig()
        host=basic_info['DB_HOST']
        uid=basic_info['DB_UID']
        pwd=basic_info['DB_PWD']
        port=basic_info['DB_PORT']
        dbnames=list_databases(host,uid,pwd,port)
        
        if dbnames:
            dbnames_lower=[dbname.lower() for dbname in dbnames]
            self.DBSelect['value']=dbnames
            select_db_name=basic_info['DB_NAME']
            if select_db_name.lower() in dbnames_lower:
                select_ind=dbnames_lower.index(select_db_name.lower())
                self.DBSelect.current(select_ind)
                self.login=True
            else:
                self.DBSelect.current(0)
            
            cur_db_name=self.DBSelect.get()
            print(f'当前选择数据库:{cur_db_name}')
            try:
                db=MySQLDB(cur_db_name,uid,pwd,host,port)
                self.tables=db.get_all_tables()
                db.close_connection()
            except Exception as e:
                print(f'初始化链接数据库错误 => {e}')
                traceback.print_exc()
                
        
    def connect_server(self):

        self.btn_conenct
        host=self.DBHostIpt.get().strip()
        uid=self.DBUidIpt.get().strip()
        pwd=self.DBPwdIpt.get().strip()
        port=int(self.DBPortIpt.get().strip())
        basic_info=get_allconfig()
        if not(host and uid and pwd and port):
            messagebox.showerror('提示','请输入完整信息')

        self.btn_conenct.config(state=DISABLED)
        select_db_name=basic_info['DB_NAME']
        dbnames=list_databases(host,uid,pwd,port)
        
        has_exist_db=False
        if dbnames:
            dbnames_lower=[dbname.lower() for dbname in dbnames]
            if select_db_name.lower() in dbnames_lower:
                has_exist_db=True
        else:
            dbnames=[]
        if not has_exist_db:
            create_database(host,uid,pwd,select_db_name)
            dbnames=[select_db_name]+dbnames

        self.DBSelect['value']=dbnames
        self.DBSelect.current(0)
        cur_db_name=self.DBSelect.get()
        update_config({'DB_NAME':cur_db_name,'DB_UID':uid,'DB_PWD':pwd,'DB_HOST':host,'DB_PORT':port})
        print(f'服务器《{host}》成功链接')
        messagebox.showinfo(f'提示',f'服务器《{host}》成功链接')
        
        self.btn_conenct.config(state=NORMAL)

    def get_conn(self):
        for jjj in range(3):
            try:
                cur_db_name=self.DBSelect.get()
                if cur_db_name =='未加载':
                    basic_info=get_allconfig()

                    cur_db_name=basic_info['DB_NAME']
                    host=basic_info['DB_HOST']
                    uid=basic_info['DB_UID']
                    pwd=basic_info['DB_PWD']
                    port=basic_info['DB_PORT']
                    return MySQLDB(cur_db_name,uid,pwd,host,port)
                else:
                    host=self.DBHostIpt.get().strip()
                    uid=self.DBUidIpt.get().strip()
                    pwd=self.DBPwdIpt.get().strip()
                    port=int(self.DBPortIpt.get().strip())
                    return MySQLDB(cur_db_name,uid,pwd,host,port)
            except Exception as e:
                print(f'链接服务器错误 => {e},正在重试...')
    

    def change_db(self):
        print(f'正在切换数据库...')
        db=self.get_conn()
        cur_db_name=self.DBSelect.get()
        self.tables=db.get_all_tables()
        db.close_connection()
        print(f'成功切换到数据库:{cur_db_name}')
        update_config({'DB_NAME':cur_db_name})

class FsbmsFrame(Frame):
    def __init__(self,master,dbfra:DBFrame):
        Frame.__init__(self,master)
        self.dbfra=dbfra
        self.session=requests.Session()
        self.createWidgets()
        self.rwname = '采集佛山产品'
    def createWidgets(self):
        basic_info=get_allconfig()
        f0=Frame(self)
        f0.pack(fill=X,padx=2,pady=2)
        Label(f0, text='佛山市标准与编码综合服务平台', fg="white", bg="#007FFF",font=("微软雅黑", 13)).pack(fill=X,padx=5)
        label_font = tkinter.font.Font(family="微软雅黑", size=10, weight="bold")
        f1=Frame(self)
        f1.pack(fill=X,padx=2,pady=2)

        
        f00=Frame(f1)
        f00.pack(fill=X,padx=2,pady=2)
        
        Label(f00, text='当前选中数据表名称:',font=label_font).pack(side=LEFT, padx=2, pady=2)
        self.TbnameIpt = Entry(f00)
        self.TbnameIpt.pack(side=LEFT, padx=2, pady=2)
        self.TbnameIpt.insert(0,basic_info['TABLE_FS_PRO'])

        f01=Frame(f1)
        f01.pack(fill=X,padx=2,pady=2)
        
        Label(f01, text='上次采集页数:').pack(side=LEFT, padx=2, pady=2)
        self.FirstPageIpt = Entry(f01,width=5)
        self.FirstPageIpt.pack(side=LEFT, padx=2, pady=2)
        self.FirstPageIpt.insert(0,basic_info['FS_LAST_CJ_PAGE'])

        Label(f01, text='每页数量:').pack(side=LEFT, padx=2, pady=2)
        self.PagesizeIpt = Entry(f01,width=5)
        self.PagesizeIpt.pack(side=LEFT, padx=2, pady=2)
        self.PagesizeIpt.insert(0,basic_info['FS_PAGE_SIZE'])

        Label(f01, text='最大采集页数:').pack(side=LEFT, padx=2, pady=2)
        self.MaxPageIpt = Entry(f01,width=7)
        self.MaxPageIpt.pack(side=LEFT, padx=2, pady=2)
        self.MaxPageIpt.insert(0,basic_info['CJ_FS_MAX_PAGE'])

        f02=Frame(f1)
        f02.pack(fill=X,padx=2,pady=2)
        Label(f02, text='循环采集:',font=label_font).pack(side=LEFT, padx=2)
        self.LoopSelect = ttk.Combobox(f02,state="readonly",width=6)
        self.LoopSelect['value']=['否','是']
        self.LoopSelect.pack(side=LEFT, padx=2)
        self.LoopSelect.current(basic_info['CJ_FS_LOOP'])

        Label(f02, text='循环间隔:',font=label_font).pack(side=LEFT, padx=2, pady=2)
        self.SleepHourIpt = Entry(f02,width=7)
        self.SleepHourIpt.pack(side=LEFT, padx=2, pady=2)
        self.SleepHourIpt.insert(0,basic_info['CJ_FS_LOOP_SLEEP'])
        Label(f02, text='小时').pack(side=LEFT, padx=2)

        Label(f02, text='定时任务:',font=label_font).pack(side=LEFT, padx=2)
        self.TimingHourSelect = ttk.Combobox(f02,state="readonly",width=6)
        self.TimingHourSelect['value']=['无定时']+[str(j) for j in range(0,24)]
        self.TimingHourSelect.pack(side=LEFT, padx=2)
        self.TimingHourSelect.current(basic_info['CJ_FS_TIMING_HOUR'])
        Label(f02, text='时').pack(side=LEFT, padx=2)

        self.TimingMinSelect = ttk.Combobox(f02,state="readonly",width=6)
        self.TimingMinSelect['value']=[str(j) for j in range(0,60)]
        self.TimingMinSelect.pack(side=LEFT, padx=2)
        self.TimingMinSelect.current(basic_info['CJ_FS_TIMING_MINUTE'])
        Label(f02, text='分').pack(side=LEFT, padx=2)


        f03=Frame(f1)
        f03.pack(fill=X,padx=2,pady=2)
        self.btn_cj=Button(f03,text='开始采集',command=lambda:Thread(target=self.begin_cj).start(),fg='#ffffff',bg='green')
        self.btn_cj.pack(side=LEFT,padx=2, pady=2)

        self.btn_timing=Button(f03,text='定时启动',command=lambda:Thread(target=self.time_begin_cj).start(),fg='#ffffff',bg='green')
        self.btn_timing.pack(side=LEFT,padx=2, pady=2)

        self.btn_cancel_timing=Button(f03,text='取消定时',command=lambda:Thread(target=self.camcel_timing).start(),fg='#ffffff',bg='green')
        self.btn_cancel_timing.pack(side=LEFT,padx=2, pady=2)

    def time_begin_cj(self):
        rwname=self.rwname

        db = self.dbfra.get_conn()
        if not db:
            messagebox.showerror('提示','请正确连接数据库')
            return
        page=self.FirstPageIpt.get().strip()
        pz=self.PagesizeIpt.get().strip()
        maxpage=self.MaxPageIpt.get().strip()
        sleep_hour=self.SleepHourIpt.get().strip()

        if not page or not maxpage or not sleep_hour or not pz:
            messagebox.showinfo('提示','请先设置采集参数')
            return

        tining_hour=self.TimingHourSelect.get()
        if tining_hour=='无定时':
            messagebox.showinfo('提示','请先设置定时时间')
            return
        
        self.cancel=False
        self.btn_timing.config(state=DISABLED)
        timing_hour=self.TimingHourSelect.get()
        timing_min=self.TimingMinSelect.get()
        update_config({'CJ_FS_TIMING_HOUR':int(timing_hour),'CJ_FS_TIMING_MINUTE':int(timing_min)})
        while True:
            timing_hour=self.TimingHourSelect.get()
            timing_min=self.TimingMinSelect.get()
            now = datetime.now()
            cur_hour=now.hour
            cur_min=now.minute

            if self.cancel:
                messagebox.showinfo('提示','成功取消定时')
                self.btn_cancel_timing.config(state=NORMAL)
                break
            if cur_hour==int(timing_hour) and cur_min==int(timing_min):
                if self.btn_cj.cget('state')=='normal':
                    print(f'《{rwname}》,当前时间:{now},目标时间:{tining_hour}:{timing_min}:00,达到目标时间启动')
                    self.begin_cj()
                else:
                    print(f'《{rwname}》,采集任务正在运行,跳过定时')
                    time.sleep(19)
            else:
                print(f'《{rwname}》,当前时间:{now},目标时间:{tining_hour}:{timing_min}:00,未达到目标时间')
                time.sleep(19)
            
        self.btn_timing.config(state=NORMAL)
    
    def camcel_timing(self):
        self.btn_cancel_timing.config(state=DISABLED)
        self.cancel=True

    def begin_cj(self):
       
        db = self.dbfra.get_conn()
        if not db:
            messagebox.showerror('提示','请正确连接数据库')
            return

        tb_name=self.TbnameIpt.get().strip()
        page=self.FirstPageIpt.get().strip()
        pz=self.PagesizeIpt.get().strip()
        maxpage=self.MaxPageIpt.get().strip()
        sleep_hour=self.SleepHourIpt.get().strip()
        if not tb_name or not page or not pz or not maxpage or not sleep_hour:
            messagebox.showinfo('提示','请先设置采集参数')
            return
        basic_info=get_allconfig()
        is_loop=self.LoopSelect.current()
        tb_name=basic_info['TABLE_FS_PRO']

        update_config({
            'TABLE_FS_PRO':tb_name,
            'FS_PAGE_SIZE':int(pz),
            'CJ_FS_LOOP':is_loop,
            'CJ_FS_LOOP_SLEEP':float(sleep_hour)
        })

        if not db.table_exists(tb_name):
            
            db.create_table(tb_name,FS_PRO_COL,[('companyName','goodsId')],['state','isuse'])

        db.close_connection()


        self.btn_cj.config(state=DISABLED)
        self.btn_timing.config(state=DISABLED)
        session=self.session
        headers={
            'Host':'api.fsbms.com',
            'Origin':'https://www.fsbms.com',
            'referer':'https://www.fsbms.com/',
            'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36'
        }
        page=int(page)
        maxpage=int(maxpage)
        pz=int(pz)
        
        rwname = '采集佛山产品'
        loop_count=1
        first_page=page
        while True:

            print(f"《{rwname}》,页数范围:{first_page}~{maxpage}页,是否循环:{is_loop},第 {loop_count} 轮")
            j=0
            while True:
                data={
                        "limit":pz,
                        "page":page,
                        "start":(page-1)*pz,
                        "sort":[{"property":"goodsId","direction":"DESC"}],
                        "goodsTypeId":"",
                        "goodsName":"",
                        "barCode":"",
                        "companyId":""
                    }

                try:
                    res=session.post('https://api.fsbms.com/fsbms-bussiness/api/frontend/website/getFoShanGoodsPage',json=data,headers=headers,timeout=30)
                    jsondata=res.json()
                    if jsondata['success']:
                        
                        if j==0:
                            totalPage=math.ceil(jsondata['total']/pz)
                            update_config({'CJ_FS_MAX_PAGE':totalPage})
                            print(f'《{rwname}》,共{totalPage}页')

                        if page>totalPage or page>maxpage:
                            break
                        
                        plist=jsondata['rows']
                        db = self.dbfra.get_conn()
                        aff=0

                        for pdata in plist:
                            rs= db.query(f'select count(*) from {tb_name} where goodsId=%s and companyName=%s',(pdata['goodsId'],pdata['companyName']))
                            if rs[0][0]==0:
                                zds=[]
                                paras=[]
                                for k,v in pdata.items():
                                    zds.append(k)
                                    if isinstance(v,list):
                                        paras.append('|'.join(v))
                                    elif k=='lastUpdateDate' and v:
                                        dt = datetime.strptime(v, "%Y-%m-%dT%H:%M:%S.%f%z")
                                        paras.append(dt.strftime("%Y-%m-%d %H:%M:%S"))
                                    else:
                                        paras.append(v)
                                zdstr=','.join(zds)
                                wstr=','.join([r'%s' for _ in paras])
                                sqlstr=f'insert into {tb_name}({zdstr}) values({wstr})'
                                aff+=db.execute_command(sqlstr,paras)

                        print(f'《{rwname}》,第{page}页,采集到 {len(plist)} 个产品,存入数据库:{aff}个,剩余:{maxpage-page}/{maxpage} 页')
                        db.close_connection()
                        page+=1
                        j+=1
                    update_config({'FS_LAST_CJ_PAGE':page})
                except Exception as e:
                    traceback.print_exc()
                    print(f'《{rwname}》,第{page}页,出现错误 =>{e}')
            
            loop_count+=1
            print(f'《{rwname}》,第{loop_count}轮循环,共采集{j}页,等待{sleep_hour}小时,开启下一轮采集...')
            if not is_loop:
                break
            else:
                time.sleep(float(sleep_hour)*3600)
                page=first_page

        messagebox.showinfo('提示',f'《{rwname}》,共循环采集{j}页')
        self.btn_cj.config(state=NORMAL)
        self.btn_timing.config(state=NORMAL)

class ZsbmsFrame(Frame):
    def __init__(self,master,dbfra:DBFrame):
        Frame.__init__(self,master)
        self.dbfra=dbfra
        self.session=requests.Session()
        self.createWidgets()
        self.rwname = '采集中山产品'
    def createWidgets(self):
        basic_info=get_allconfig()
        f0=Frame(self)
        f0.pack(fill=X,padx=2,pady=2)
        Label(f0, text='中山市物品编码商品信息数据服务平台', fg="white", bg="#007FFF",font=("微软雅黑", 13)).pack(fill=X,padx=5)
        label_font = tkinter.font.Font(family="微软雅黑", size=10, weight="bold")
        f1=Frame(self)
        f1.pack(fill=X,padx=2,pady=2)

        
        f00=Frame(f1)
        f00.pack(fill=X,padx=2,pady=2)
        
        Label(f00, text='当前选中数据表名称:',font=label_font).pack(side=LEFT, padx=2, pady=2)
        self.TbnameIpt = Entry(f00)
        self.TbnameIpt.pack(side=LEFT, padx=2, pady=2)
        self.TbnameIpt.insert(0,basic_info['TABLE_ZS_PRO'])

        f01=Frame(f1)
        f01.pack(fill=X,padx=2,pady=2)
        
        Label(f01, text='上次采集页数:').pack(side=LEFT, padx=2, pady=2)
        self.FirstPageIpt = Entry(f01,width=5)
        self.FirstPageIpt.pack(side=LEFT, padx=2, pady=2)
        self.FirstPageIpt.insert(0,basic_info['ZS_LAST_CJ_PAGE'])

        Label(f01, text='每页数量:').pack(side=LEFT, padx=2, pady=2)
        self.PagesizeIpt = Entry(f01,width=5)
        self.PagesizeIpt.pack(side=LEFT, padx=2, pady=2)
        self.PagesizeIpt.insert(0,basic_info['ZS_PAGE_SIZE'])

        Label(f01, text='最大采集页数:').pack(side=LEFT, padx=2, pady=2)
        self.MaxPageIpt = Entry(f01,width=7)
        self.MaxPageIpt.pack(side=LEFT, padx=2, pady=2)
        self.MaxPageIpt.insert(0,basic_info['CJ_ZS_MAX_PAGE'])

        f02=Frame(f1)
        f02.pack(fill=X,padx=2,pady=2)
        Label(f02, text='循环采集:',font=label_font).pack(side=LEFT, padx=2)
        self.LoopSelect = ttk.Combobox(f02,state="readonly",width=6)
        self.LoopSelect['value']=['否','是']
        self.LoopSelect.pack(side=LEFT, padx=2)
        self.LoopSelect.current(basic_info['CJ_ZS_LOOP'])

        Label(f02, text='循环间隔:',font=label_font).pack(side=LEFT, padx=2, pady=2)
        self.SleepHourIpt = Entry(f02,width=7)
        self.SleepHourIpt.pack(side=LEFT, padx=2, pady=2)
        self.SleepHourIpt.insert(0,basic_info['CJ_ZS_LOOP_SLEEP'])
        Label(f02, text='小时').pack(side=LEFT, padx=2)

        Label(f02, text='定时任务:',font=label_font).pack(side=LEFT, padx=2)
        self.TimingHourSelect = ttk.Combobox(f02,state="readonly",width=6)
        self.TimingHourSelect['value']=['无定时']+[str(j) for j in range(0,24)]
        self.TimingHourSelect.pack(side=LEFT, padx=2)
        self.TimingHourSelect.current(basic_info['CJ_ZS_TIMING_HOUR'])
        Label(f02, text='时').pack(side=LEFT, padx=2)

        self.TimingMinSelect = ttk.Combobox(f02,state="readonly",width=6)
        self.TimingMinSelect['value']=[str(j) for j in range(0,60)]
        self.TimingMinSelect.pack(side=LEFT, padx=2)
        self.TimingMinSelect.current(basic_info['CJ_ZS_TIMING_MINUTE'])
        Label(f02, text='分').pack(side=LEFT, padx=2)


        f03=Frame(f1)
        f03.pack(fill=X,padx=2,pady=2)
        self.btn_cj=Button(f03,text='开始采集',command=lambda:Thread(target=self.begin_cj).start(),fg='#ffffff',bg='green')
        self.btn_cj.pack(side=LEFT,padx=2, pady=2)

        self.btn_timing=Button(f03,text='定时启动',command=lambda:Thread(target=self.time_begin_cj).start(),fg='#ffffff',bg='green')
        self.btn_timing.pack(side=LEFT,padx=2, pady=2)

        self.btn_cancel_timing=Button(f03,text='取消定时',command=lambda:Thread(target=self.camcel_timing).start(),fg='#ffffff',bg='green')
        self.btn_cancel_timing.pack(side=LEFT,padx=2, pady=2)

    def time_begin_cj(self):
        rwname=self.rwname

        db = self.dbfra.get_conn()
        if not db:
            messagebox.showerror('提示','请正确连接数据库')
            return
        page=self.FirstPageIpt.get().strip()
        pz=self.PagesizeIpt.get().strip()
        maxpage=self.MaxPageIpt.get().strip()
        sleep_hour=self.SleepHourIpt.get().strip()

        if not page or not maxpage or not sleep_hour or not pz:
            messagebox.showinfo('提示','请先设置采集参数')
            return

        tining_hour=self.TimingHourSelect.get()
        if tining_hour=='无定时':
            messagebox.showinfo('提示','请先设置定时时间')
            return
        
        self.cancel=False
        self.btn_timing.config(state=DISABLED)
        timing_hour=self.TimingHourSelect.get()
        timing_min=self.TimingMinSelect.get()
        update_config({'CJ_ZS_TIMING_HOUR':int(timing_hour),'CJ_ZS_TIMING_MINUTE':int(timing_min)})
        while True:
            timing_hour=self.TimingHourSelect.get()
            timing_min=self.TimingMinSelect.get()
            now = datetime.now()
            cur_hour=now.hour
            cur_min=now.minute

            if self.cancel:
                messagebox.showinfo('提示','成功取消定时')
                self.btn_cancel_timing.config(state=NORMAL)
                break
            if cur_hour==int(timing_hour) and cur_min==int(timing_min):
                if self.btn_cj.cget('state')=='normal':
                    print(f'《{rwname}》,当前时间:{now},目标时间:{tining_hour}:{timing_min}:00,达到目标时间启动')
                    self.begin_cj()
                else:
                    print(f'《{rwname}》,采集任务正在运行,跳过定时')
                    time.sleep(19)
            else:
                print(f'《{rwname}》,当前时间:{now},目标时间:{tining_hour}:{timing_min}:00,未达到目标时间')
                time.sleep(19)
            
        self.btn_timing.config(state=NORMAL)
    
    def camcel_timing(self):
        self.btn_cancel_timing.config(state=DISABLED)
        self.cancel=True

    def begin_cj(self):
       
        db = self.dbfra.get_conn()
        if not db:
            messagebox.showerror('提示','请正确连接数据库')
            return

        tb_name=self.TbnameIpt.get().strip()
        page=self.FirstPageIpt.get().strip()
        pz=self.PagesizeIpt.get().strip()
        maxpage=self.MaxPageIpt.get().strip()
        sleep_hour=self.SleepHourIpt.get().strip()
        if not tb_name or not page or not pz or not maxpage or not sleep_hour:
            messagebox.showinfo('提示','请先设置采集参数')
            return
        basic_info=get_allconfig()
        is_loop=self.LoopSelect.current()
        tb_name=basic_info['TABLE_ZS_PRO']

        update_config({
            'TABLE_ZS_PRO':tb_name,
            'ZS_PAGE_SIZE':int(pz),
            'CJ_ZS_LOOP':is_loop,
            'CJ_ZS_LOOP_SLEEP':float(sleep_hour)
        })

        if not db.table_exists(tb_name):
            
            db.create_table(tb_name,ZS_PRO_COL,[('companyName','goodsId')],['state','isuse'])

        db.close_connection()


        self.btn_cj.config(state=DISABLED)
        self.btn_timing.config(state=DISABLED)
        session=self.session
        headers={
            'Host':'api.fsbms.com',
            'Origin':'https://www.zsbms.net.cn',
            'referer':'https://www.zsbms.net.cn/',
            'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36'
        }
        page=int(page)
        maxpage=int(maxpage)
        pz=int(pz)
        
        rwname = self.rwname
        loop_count=1
        first_page=page
        while True:

            print(f"《{rwname}》,页数范围:{first_page}~{maxpage}页,是否循环:{is_loop},第 {loop_count} 轮")
            j=0
            while True:
                data={
                        "limit":pz,
                        "page":page,
                        "start":(page-1)*pz,
                        "sort":[{"property":"goodsId","direction":"DESC"}],
                        "goodsTypeId":"",
                        "goodsName":"",
                        "barCode":"",
                        "companyId":""
                    }

                try:

                    res=session.post('https://api.fsbms.com/zsbms-bussiness/api/frontend/website/getFoShanGoodsPage',json=data,headers=headers,timeout=30)
                    jsondata=res.json()
                    if jsondata['success']:
                        
                        if j==0:
                            totalPage=math.ceil(jsondata['total']/pz)
                            update_config({'CJ_ZS_MAX_PAGE':totalPage})
                            print(f'《{rwname}》,共{totalPage}页')

                        if page>totalPage or page>maxpage:
                            break
                        
                        plist=jsondata['rows']
                        db = self.dbfra.get_conn()
                        aff=0

                        for pdata in plist:
                            rs= db.query(f'select count(*) from {tb_name} where goodsId=%s and companyName=%s',(pdata['goodsId'],pdata['companyName']))
                            if rs[0][0]==0:
                                zds=[]
                                paras=[]
                                for k,v in pdata.items():
                                    zds.append(k)
                                    if isinstance(v,list):
                                        paras.append('|'.join(v))
                                    elif k=='lastUpdateDate' and v:
                                        dt = datetime.strptime(v, "%Y-%m-%dT%H:%M:%S.%f%z")
                                        paras.append(dt.strftime("%Y-%m-%d %H:%M:%S"))
                                    else:
                                        paras.append(v)
                                zdstr=','.join(zds)
                                wstr=','.join([r'%s' for _ in paras])
                                sqlstr=f'insert into {tb_name}({zdstr}) values({wstr})'
                                aff+=db.execute_command(sqlstr,paras)

                        print(f'《{rwname}》,第{page}页,采集到 {len(plist)} 个产品,存入数据库:{aff}个,剩余:{maxpage-page}/{maxpage} 页')
                        db.close_connection()
                        page+=1
                        j+=1
                    update_config({'ZS_LAST_CJ_PAGE':page})
                except Exception as e:
                    traceback.print_exc()
                    print(f'《{rwname}》,第{page}页,出现错误 =>{e}')
            
            loop_count+=1
            print(f'《{rwname}》,第{loop_count}轮循环,共采集{j}页,等待{sleep_hour}小时,开启下一轮采集...')
            if not is_loop:
                break
            else:
                time.sleep(float(sleep_hour)*3600)
                page=first_page

        messagebox.showinfo('提示',f'《{rwname}》,共循环采集{j}页')
        self.btn_cj.config(state=NORMAL)
        self.btn_timing.config(state=NORMAL)


 
import tkinter
list_win = tkinter.Tk()
list_win.wm_geometry("800x650")
list_win.title('主页')
ProFrame(list_win).pack(fill=X, padx=3, pady=3)
list_win.mainloop()